﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace br.ita.CTC34.GLCToAPConverter
{
    public class IOManager
    {
        public static GLC parseInputFile(string inputPath)
        {
            GLC glc = new GLC();

            StreamReader sr = null;

            try
            {
                sr = new StreamReader(inputPath);
            }
            catch (DirectoryNotFoundException ex)
            {
                Console.WriteLine(ex.StackTrace);
            }
            catch (FileNotFoundException ex)
            {
                Console.WriteLine(ex.StackTrace);
            }

            glc.initialSymbol = getInitialSymbol(glc, sr);
            glc.emptyStringSymbol = getEmptyStringSymbol(glc, sr);
            glc.endSymbols = getEndSymbols(glc, sr);
            glc.nonEndSymbols = getNonEndSymbols(glc, sr);
            glc.productions = getProductions(glc, sr);
            sr.Close();

            return glc;
        }

        public static void writeOutputFile(Automata outputAutomata, string outputFileName)
        {
            StreamWriter file = new StreamWriter(outputFileName);

            try
            {
                file.Write(outputAutomata.getAutomataOutputFileContent());
            }
            catch (IOException ex)
            {
                Console.WriteLine(ex.StackTrace);
            }
            
            file.Close();
        }

        private static string getInitialSymbol(GLC glc, StreamReader sr)
        {
            String initialSymbol = "";
            
            if (!sr.EndOfStream)
            {
                initialSymbol = sr.ReadLine();
                initialSymbol = initialSymbol.Trim();
            }

            return initialSymbol;
        }

        private static string getEmptyStringSymbol(GLC glc, StreamReader sr)
        {
            String emptyStringSymbol = "";

            if (!sr.EndOfStream)
            {
                emptyStringSymbol = sr.ReadLine();
                emptyStringSymbol = emptyStringSymbol.Trim();
            }

            return emptyStringSymbol;
        }

        private static ArrayList getEndSymbols(GLC glc, StreamReader sr)
        {
            String endSymbolsRaw = "";
            ArrayList endSymbols = new ArrayList();

            if (!sr.EndOfStream)
            {
                endSymbolsRaw = sr.ReadLine();
                endSymbolsRaw = endSymbolsRaw.Trim();

                String[] endSymbolsSplit = endSymbolsRaw.Split(' ');

                for (int i = 0; i < endSymbolsSplit.Length; i++)
                {
                    string endSymbol = endSymbolsSplit[i];
                    endSymbols.Add(endSymbol);
                }
            }

            return endSymbols;
        }

        private static ArrayList getNonEndSymbols(GLC glc, StreamReader sr)
        {
            String nonEndSymbolsRaw = "";
            ArrayList nonEndSymbols = new ArrayList();

            if (!sr.EndOfStream)
            {
                nonEndSymbolsRaw = sr.ReadLine();
                nonEndSymbolsRaw = nonEndSymbolsRaw.Trim();

                String[] nonEndSymbolsSplit = nonEndSymbolsRaw.Split(' ');

                for (int i = 0; i < nonEndSymbolsSplit.Length; i++)
                {
                    string nonEndSymbol = nonEndSymbolsSplit[i];
                    nonEndSymbols.Add(nonEndSymbol);
                }
            }

            return nonEndSymbols;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="glc"></param>
        /// <param name="sr"></param>
        /// <returns>HashTable<char, ArrayList></returns>
        private static Hashtable getProductions(GLC glc, StreamReader sr)
        {
            Hashtable productions = new Hashtable();

            while (!sr.EndOfStream)
            {
                String productionsRaw = "";

                productionsRaw = sr.ReadLine();
                productionsRaw = productionsRaw.Trim();

                String[] productionsSplit = productionsRaw.Split('>');

                string generator = productionsSplit[0];
                String sentence = productionsSplit[1].Trim();

                if (!productions.ContainsKey(generator))
                {
                    ArrayList sentencesFromAProduction = new ArrayList();
                    sentencesFromAProduction.Add(sentence);
                    productions.Add(generator, sentencesFromAProduction);
                }
                else
                {
                    ((ArrayList) productions[generator]).Add(sentence);
                }
            }

            return productions;
        }
    }
}